#include "Common.h"
#include "String.h"
#include "SharedPtr.h"
#include "ResourceManager.h"
#include "Database/DatabaseEnv.h"
#include "StringConverter.h"
#include "NGLog.h"
#include "MersenneTwister.h"
#include "ScriptMgr.h"
#include "Threading/Mutex.h"
#include "Util.h"
#include "Message.h"
#include "Effects.h"
#include "WorldPacket.h"
#include "Character.h"
#include "CharManager.h"
#include "Regions.h"
#include "RegionManager.h"
#include "WSSocket.h"
#include "PGWorldAIInterface.h"
#include "PGAIScript.h"
#include "GameDefine.h"
#include ENUM_PATH
#include LOGIC_MGR_PATH
#include XMLDATA_MGR_PATH
#include PROTOCOLS_MGR_PATH




namespace AIScript 
{
	//-----------------------------------------------------------------------
	PGTownInterface::PGTownInterface(Resource * pUnit):AIInterface(pUnit)
	{
		m_AIType = AITYPE_TOWN;
	}

	PGTownInterface::~PGTownInterface(void)
	{
	}
	
	//-----------------------------------------------------------------------
	void 	PGTownInterface::Load(void)
	{
		AIInterface::Load();
		lastCheckTime = 0;
		uint32 minChns = sXmlDataMgr.GetConfXMLValue("INIT_CHN_NUM");
		for (uint32 i = 0; i < minChns; ++i)
		{
			ChannelPtr pChn = sPubLogic.CreateNewChannel(m_Unit,m_lstChannels.size() + 1);
			if (!pChn.isNull())
			{
				m_lstChannels.push_back(pChn);
			}
		}
	}
	
	//-----------------------------------------------------------------------
	uint8 PGTownInterface::JoinOneChannel(CharPtr & pChr, const uint32 chnId)
	{
	return 0;
	}
	bool PGTownInterface::JoinRoom(CharPtr &pChr)
	{

		if (pChr.isNull())
		{
			Log.Debug("PGTownInterface::JoinRoom", "pChr is null");
			return false;
		}

		uint32 result = en_JoinRoom_Faild;
		// 判断玩家是否已经在某个房间里
		PGCreatureInterface *pChrAiInfe = TO_CREATURE_INTERFACE(pChr->getAIInterface());
		if (!pChrAiInfe)
		{
			Log.Debug("PGTownInterface::JoinRoom", "pChrAiInfe is null");
			return false;
		}

		WorldPacket packet;
		TownPtr pTown = pChrAiInfe->GetTown();
		if (!pTown.isNull())
		{
			if (pTown->getHandle() != m_Unit->getHandle())
			{

				result = en_JoinRoom_InOtherRoom;
			}
			else
			{
				ChannelPtr pChn = pChrAiInfe->GetChannelPtr();
				if (!pChn.isNull())
				{

					PGChannelInterface *pChnAiInfe = TO_CHANNEL_INTERFACE(pChn->getAIInterface());

					if (pChnAiInfe)
					{
						if (sProtocolsMgr.CreateEnterTownPacket(&packet, (uint32)m_Unit->getHandle(), en_JoinRoom_Ok))
							sGLMgr.SendProtocolsToChr(pChr, &packet);

						Log.Debug("PGTownInterface::JoinRoom", " PGTownInterface   JoinChannel 加入牌桌");

						return pChnAiInfe->JoinChannel(pChr);
					}
				}
				result = en_JoinRoom_InOtherRoom;
			}
		}

		// 新玩家，判断其是否能加入该房间
		if (en_JoinRoom_Faild == result)
			result = CheckCondition(pChr);
		if (sProtocolsMgr.CreateEnterTownPacket(&packet, (uint32)m_Unit->getHandle(), result))
			sGLMgr.SendProtocolsToChr(pChr, &packet);
		if (en_JoinRoom_Ok == result)
		{
			pChrAiInfe->SetTown(m_Unit);
			if (pChr->isNPC())
			{
				pChrAiInfe->GameReady();
				Log.Debug("PGTownInterface::JoinRoom", "机器人准备！！！");
			}

			UpdatePlayerNumber(true);
			return true;
		}
		else
		{
			Log.Debug("PGTownInterface::JoinRoom", "result is not ok");
		}

		Log.Debug("PGTownInterface::JoinRoom", "result[%u] is not ok 条件不满足！！！", result);

		return false;
	}
	//-----------------------------------------------------------------------
	uint8 PGTownInterface::LeaveChannel(CharPtr & pChr, bool bOffline)
	{	
		//
		if(pChr.isNull())
			return en_LeaveTable_Faild;	
		PGCreatureInterface * pChrAIInf = TO_CREATURE_INTERFACE(pChr->getAIInterface());
		if (NULL == pChrAIInf)
			return en_LeaveTable_Faild;
		// 找到牌桌
		ChannelPtr pChn = pChrAIInf->GetChannelPtr();
		PGChannelInterface *pChnAIInf;
		
		if (pChn.isNull() || NULL == (pChnAIInf = TO_CHANNEL_INTERFACE(pChn->getAIInterface())))
		{
			
			pChrAIInf->SetTownAndChannelId();
			return en_LeaveTable_Faild;
		}
		//assert(0);
		uint8 result = pChnAIInf->ExitChannel(pChr, bOffline);
		Log.Debug("PGTownInterface Test", "/////////LeaveTown[%u] pChr[%u] num[%u, %u]", 
				m_Unit->getHandle(), pChr->getHandle(), m_Unit->getUInt32Field("num"), m_curNumber.GetVal());
		return result;
	}
	//-----------------------------------------------------------------------
	void PGTownInterface::UpdatePlayerNumber(bool bAdd)
	{
		if (bAdd) 
			m_Unit->setUInt32Field("num", ++m_curNumber);
		else
			m_Unit->setUInt32Field("num", --m_curNumber);
		Log.Debug("PGTownInterface::UpdatePlayerNumber", "/////////Town[%u] current num[%u, %u]", m_Unit->getHandle(), m_Unit->getUInt32Field("num"), m_curNumber.GetVal());
	}
	//-----------------------------------------------------------------------
	void PGTownInterface::Update(const uint32 & p_time)
	{
		AIInterface::Update(p_time);
		// 每隔5秒检测牌桌，移除待删除的，全满则新增
		WGS_TW_CHNLIST_INNER_LOCK
		if (0 == lastCheckTime || time(0) - lastCheckTime >= sXmlDataMgr.GetConfXMLValue("TWCK_TIME"))
		{
			uint32 minChns = sXmlDataMgr.GetConfXMLValue("INIT_CHN_NUM");
			bool bCanRemove = false;
			if (m_lstChannels.size() > minChns)
			{
				bCanRemove = true;
			}
			else if (m_lstChannels.size() < minChns)
			{
				ChannelPtr pChn = sPubLogic.CreateNewChannel(m_Unit,m_lstChannels.size() + 1);
				if (!pChn.isNull())
				{
					m_lstChannels.push_back(pChn);
				}
			}
			bool bAllFull = true;
			std::list<ChannelPtr>::iterator iter = m_lstChannels.begin(), iterTemp;
			for (; iter != m_lstChannels.end(); )
			{
				if (bCanRemove && en_ChannelStatus_WaitDelete == (*iter)->getUInt32Field("status"))
				{
					iterTemp = iter;
					++iter;
					// 移除牌桌
					sResourceControlMgr.destroyResource((ResourceProxy)(*iterTemp), 500);
					m_lstChannels.erase(iterTemp);
					continue;
				}
				if (bAllFull && (*iter)->getUInt32Field("timeout") < uint32(m_Unit->getUInt32Field("max_num") * 0.01f * sXmlDataMgr.GetConfXMLValue("CREAT_NEWCHN")))
					bAllFull = false;
				++iter;
			}
			if (bAllFull)
			{
				ChannelPtr pChn = sPubLogic.CreateNewChannel(m_Unit,m_lstChannels.size() + 1);
				if (!pChn.isNull())
				{
					m_lstChannels.push_back(pChn);
				}
			}
			lastCheckTime = time(0);
		}
	}	
	//-----------------------------------------------------------------------
	ChannelPtr PGTownInterface::GetChannelPtr(const uint32 channelId, uint32 &tableIndex)
	{
		// 加锁
		WGS_TW_CHNLIST_INNER_LOCK
		ChannelPtr pChn;
		std::list<ChannelPtr>::iterator iter = m_lstChannels.begin();
		for (; iter != m_lstChannels.end(); ++iter)
		{
			if ((*iter).isNull())
				continue;
			++tableIndex;
			if ((*iter)->getHandle() == channelId)
			{
				pChn = *iter; 
				if (en_ChannelStatus_Run != pChn->getUInt32Field("status"))
					pChn->setUInt32Field("status", en_ChannelStatus_Run);
				break;
			}
		}
		return pChn;
	}
	//-----------------------------------------------------------------------
	ChannelPtr PGTownInterface::GetChannelPtr(const uint32 channelId)
	{
		// 加锁
		WGS_TW_CHNLIST_INNER_LOCK
		ChannelPtr pChn;
		std::list<ChannelPtr>::iterator iter = m_lstChannels.begin();
		for (; iter != m_lstChannels.end(); ++iter)
		{
			if ((*iter).isNull())
				continue;
			if ((*iter)->getHandle() == channelId)
			{
				pChn = *iter; 
				if (en_ChannelStatus_Run != pChn->getUInt32Field("status"))
					pChn->setUInt32Field("status", en_ChannelStatus_Run);
				break;
			}
		}
		return pChn;
	}
	//-----------------------------------------------------------------------
	ChannelPtr PGTownInterface::GetBestChannelPtr(uint32 &tableIndex)
	{
		// 加锁
		WGS_TW_CHNLIST_INNER_LOCK
		ChannelPtr pChn;
		uint32 index = 0;
		// uint32 maxNum = m_Unit->getUInt32Field("max_num");
		uint32 createNum = uint32(m_Unit->getUInt32Field("max_num") * 0.01f * sXmlDataMgr.GetConfXMLValue("CREAT_NEWCHN"));
		std::list<ChannelPtr>::iterator iter = m_lstChannels.begin();
		for (; iter != m_lstChannels.end(); ++iter)
		{
			if ((*iter).isNull())
				continue;
			++index;
			// 获取牌桌人数
			uint32 number = (*iter)->getUInt32Field("timeout");
			if (pChn.isNull() && number < createNum)
			{
				pChn = *iter;
				tableIndex = index;
			}
			else
			{
				// 如果当前人数小于创建新牌桌阀值且当前人数大于当前最优牌桌人数，替换之
				if (number < createNum && number > pChn->getUInt32Field("timeout"))
				{
					pChn = *iter;
					tableIndex = index;
				}
			}
		}
		if (pChn.isNull())
		{
			pChn = sPubLogic.CreateNewChannel(m_Unit,m_lstChannels.size() + 1);
			if (!pChn.isNull())
			{
				m_lstChannels.push_back(pChn);
				tableIndex = ++index;
			}
		}
		else if (en_ChannelStatus_Run != pChn->getUInt32Field("status"))
			pChn->setUInt32Field("status", en_ChannelStatus_Run);
		return pChn;
	}
	//-----------------------------------------------------------------------
	uint32 PGTownInterface::CheckCondition(CharPtr &pChr, bool bFirst)
	{
		if (pChr.isNull())
		{
			Log.Debug("PDKAITownInterface::CheckCondition", "pChr is null");
			return en_JoinRoom_Faild;
		}

		// 检测进房金额限制
		if (pChr->getUInt32Field("speed") < m_Unit->getUInt32Field("town_hp"))
		{
			Log.Debug("PDKAITownInterface::CheckCondition", "进房金额限制");
			return en_JoinRoom_ChipsScanty;
		}

		if (m_Unit->getUInt32Field("palmy") > 0 && pChr->getUInt32Field("speed") > m_Unit->getUInt32Field("palmy"))
		{
			Log.Debug("PDKAITownInterface::CheckCondition", "钱超出了房间限制最大值");
			return en_JoinRoom_ChipsGreater;
		}

		if (bFirst)
		{
			// 检查等级
			if (pChr->getUInt32Field("lv") < m_Unit->getUInt32Field("need_lv"))
			{
				Log.Debug("PDKAITownInterface::CheckCondition", "等级不够");
				return en_JoinRoom_LevelLittle;
			}

			// 检查人满
			if (m_Unit->getUInt32Field("max_num") > 0 && m_curNumber.GetVal() >= m_Unit->getUInt32Field("max_num"))
			{
				Log.Debug("PDKAITownInterface::CheckCondition", "房间人数已满");
				return en_JoinRoom_Full;
			}
		}
		return en_JoinRoom_Ok;
	}

	//-----------------------------------------------------------------------
	void PGTownInterface::Broadcast(WorldPacket *pPacket)
	{
		if (NULL == pPacket)
			return;
		WGS_TW_CHNLIST_INNER_LOCK
		ChannelPtr pChn;
		std::list<ChannelPtr>::iterator iter = m_lstChannels.begin();
		for (; iter != m_lstChannels.end(); ++iter)
		{
			if ((*iter).isNull())
				continue;
			//PGChannelInterface *pChnAIInf = TO_CHANNEL_INTERFACE((*iter)->getAIInterface());
		//	if (NULL != pChnAIInf)
				//pChnAIInf->Broadcast(pPacket);
		}
	}
	//-----------------------------------------------------------------------
	void PGTownInterface::GetTableList(std::list<ChannelPtr> &lstChannel)
	{
		WGS_TW_CHNLIST_INNER_LOCK
		lstChannel.assign(m_lstChannels.begin(), m_lstChannels.end());
	}
}
